package com.demo.thread.service.student.impl;

import com.demo.thread.entity.student.Student;
import com.demo.thread.mapper.student.StudentMapper;
import com.demo.thread.service.student.IStudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class StudentServiceImpl implements IStudentService {

    @Resource
    private StudentMapper studentMapper;
    @Resource
    private PlatformTransactionManager  transactionManager;

    /**
     * 1.id不是自增，我的是long类型
     * 2.直接用的时间戳，这不是重点自己可以修改成uuid
     */
    @Transactional
    @Override
    public void saveStudent() {
        Student student = Student.builder().name("张三").score(90).build();
        studentMapper.insert(student);
        new Thread(()->{
            Student s1 = Student.builder().name("李四").score(99).build();
            studentMapper.insert(s1);
        }).start();
//        throw new RuntimeException("手动抛出异常");
    }


    public void saveStudentUpgrade() {
        //获取学生数据
        List<Student> students = getMockStudents();
        //创建缓存线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        //创建计数器
        CountDownLatch latch = new CountDownLatch(students.size());
        //异常标识默认为false，如果子线程报错，标识设置为true
        AtomicBoolean isError = new AtomicBoolean(false);
        //按照学生数量开启多个线程
        for (Student student : students) {
            executorService.execute(() -> {
                TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
                transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                    protected void doInTransactionWithoutResult(TransactionStatus status) {
                        try {
                            //通过TransactionTemplate.execute()方法执行插入操作
                            studentMapper.insert(student);
                            //制造异常
                            if (student.getName().equals("李一")) {
                                throw new RuntimeException("手动抛出异常");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            isError.set(true);
                        }finally {
                            latch.countDown();
                        }
                        //等待其他线程执行
                        try {
                            latch.await();
                            if(isError.get()){
                                status.setRollbackOnly();
                            }
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            });
        }
        try {
            //主线程等待其他子线程执行完毕
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }

    public List<Student> getMockStudents(){
        List<Student> list = new ArrayList<>();
        list.add(Student.builder().name("李一").score(96).build());
        list.add(Student.builder().name("李二").score(97).build());
        list.add(Student.builder().name("李三").score(98).build());
        return list;
    }





}
